// 第一排的位置固定，所有排的位置固定
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;


const int N = 7;

char light[N][N];
char status[N][N];
int c_num[N][N];
int n;

void print()
{
    for(int i = 1; i <= 5; ++i)
    {
        for(int j = 1; j <= 5; ++j)
            cout << status[i][j] << ' ';
        cout << endl;
    }
    
}


inline void _change(int i, int j)
{
    if(status[i][j] == '1')
        status[i][j] = '0';
    else
        status[i][j] = '1';
}

void change_op(int i, int j)
{
    _change(i, j);
    _change(i - 1, j);
    _change(i + 1, j);
    _change(i, j + 1);
    _change(i, j - 1);
}

int solve()
{
   // 先把第一行的所有状态找到
   // 指数型dfs
   // 枚举第一行的所有可能性，可以利用位操作的性质进行枚举
   int ans = 10;
   for(int t = 0; t < (1 << 5); ++t)
   {
       memcpy(status, light, sizeof light);
       int num = 0;
       // 先调试第一层的
       for(int k = 0; k < 5; ++k)
        if(t & (1 << k))
        {
            // 说明这栈灯被拉了
            change_op(1, k + 1);
            ++num;
        }
        // 接下来枚举下面几层的可能性
        for(int i = 2; i <= 5; ++i)
            for(int j = 1; j <= 5; ++j)
            {
                if(status[i - 1][j] == '0')
                {
                    change_op(i, j);
                    num++;
                }
            }
        bool dark = false;
        // 这里不能用continue啊
        // continue是跳过当前循环，所以最后的赋值还是会进行的！！！
        for(int i = 1; i <= 5; ++i)
            if(status[5][i] == '0')
            {
                dark = true;
                break;
            }
        if(!dark) ans = min(ans, num);
   }
   if(ans > 6) return -1;
   else return ans;
}

int main()
{
    cin >> n;
    while(n--)
    {
        for(int i = 1; i <= 5; ++i)
            cin >> (light[i] + 1);
        int n = solve();
        cout << n << endl;
    }
    
}